package com.noahsloan.nutils.collections;

import com.noahsloan.nutils.Equals;
import com.noahsloan.nutils.Hasher;
import com.noahsloan.nutils.Utils;

/**
 * Base class for classes needing to wrap values to replace their hashCode and
 * equals methods.
 * 
 * @author noah
 * 
 * @param <T>
 */
public class ExternalHashBase<T> implements Equals<T, T>, Hasher<T> {

	public class HashWrapper {
		public final T value;

		private HashWrapper(T value) {
			super();
			Utils.notNull(value, "value");
			this.value = value;
		}

		@Override
		public int hashCode() {
			return hash.hashCode(value);
		}

		/**
		 * Uses the external equals. If obj is not of the same HashWrapper
		 * class, returns false.
		 */
		@Override
		public boolean equals(Object obj) {
			if (obj == null || obj.getClass() != HashWrapper.class) {
				return false;
			}
			return equals.equals(value, ((HashWrapper) obj).value);
		}
		
		@Override
		public String toString() {
			return value.toString();
		}
	}

	protected final Hasher<? super T> hash;

	protected final Equals<? super T, ? super T> equals;

	public ExternalHashBase(Hasher<? super T> hash,
			Equals<? super T, ? super T> equals) {
		super();
		this.hash = hash;
		this.equals = equals;
	}

	public HashWrapper wrap(T value) {
		return new HashWrapper(value);
	}

	public boolean equals(T a, T b) {
		return equals.equals(a, b);
	}

	public int hashCode(T t) {
		return hash.hashCode(t);
	}
}
